import type { FetchResponse } from 'ofetch'
import type { UseFetchOptions } from '#app'

export interface ResOptions<T> {
	status: string
	data: T
	data2?: {}
	msg: string
}

function handleError<T>(response: FetchResponse<ResOptions<T>> & FetchResponse<ResponseType>) {
	const err = (text?: string) => {
		ElMessage.error({
			message: response?._data?.msg ?? text,
		})
	}
	if (!response._data) {
		err('请求超时，服务器无响应！')
		return
	}

	// const userStore = useUserStore()
	const handleMap: { [key: number]: () => void } = {
		404: () => err('服务器资源不存在'),
		500: () => err('服务器内部错误'),
		403: () => err('没有权限访问该资源'),
		401: () => {
			err('登录状态已过期，需要重新登录')
			// userStore.clearUserInfo()
			// TODO 跳转实际登录页
			navigateTo('/')
		},
	}
	handleMap[response.status] ? handleMap[response.status]() : err(response._data.msg || '未知错误！')
}

function fetch<T>(url: string, method: 'get' | 'post' | 'put' | 'delete', params?: any, opts?: UseFetchOptions<any>) {
	const defaultOptions: UseFetchOptions<any> = {
		method,
		// 添加baseURL,nuxt3环境变量要从useRuntimeConfig里面取
		baseURL: useRuntimeConfig().public.baseURL || '/api',
		// 查询参数
		query: method === 'get' ? params : undefined, //temp hook
		// post 参数
		body: method !== 'get' ? JSON.stringify(params) : undefined,

		// 请求拦截器
		onRequest({ request, options }) {
			options.headers = (options.headers || {}) as { [key: string]: string } // 转 map
			options.headers['Content-Type'] = 'application/json;charset=UTF-8'

			// console.log('options:', options)

			// 添加请求头,没登录不携带token
			// const userStore = useUserStore()
			// if (!userStore.isLogin) return
			// options.headers = new Headers(options.headers)
			// options.headers.set('Authorization', `Bearer ${userStore().getToken}`)
		},
		// 响应拦截
		onResponse({ response, options }) {
			// if (response.headers.get('content-disposition') && response.status === 200) return response
			const isGET = (options.method as string).toUpperCase() == 'GET'

			if (response._data.status !== 'success') {
				handleError<T>(response)
				if (isGET) return Promise.reject(response._data.msg)

				response._data = false
				return Promise.resolve(false)
			}
			if (isGET) response._data = response._data.data
			else response._data = true // 成功: POST/PUT 等返回 true

			// console.log('resp:', options.method, url, '=>', isGET ? (response._data ? '成功' : '无数据') : response._data)
			// console.log('响应:', options.method, url, params ? params : '', '=>', response._data)
			return
		},

		// 错误处理
		onResponseError({ response }) {
			handleError<T>(response)
			return Promise.reject(response?._data ?? null)
		},
	}
	// return useFetch<ResOptions<T>>(url, useMerge(defaultOptions, opts) as any)
	return useFetch<T>(url, useMerge(defaultOptions, opts) as any)
}

// 自动导出
export const useHttp = {
	get: <T>(url: string, params?: any, pageInfo?: any, appendStr?: string, option?: UseFetchOptions<any>) => {
		let q = { qry: params, pageInfo: pageInfo, append: appendStr }
		if (!params) delete q.qry
		if (!pageInfo) delete q.pageInfo
		if (!appendStr) delete q.append
		return fetch<T>(url, 'get', q, option)
	},

	// immediate: false
	getLazy: <T>(url: string, params?: any, pageInfo?: any, appendStr?: string) => {
		let q = { qry: params, pageInfo: pageInfo, append: appendStr }
		if (!params) delete q.qry
		if (!pageInfo) delete q.pageInfo
		if (!appendStr) delete q.append
		return fetch<T>(url, 'get', q, { immediate: false })
	},

	post: <T>(url: string, body?: any, option?: UseFetchOptions<any>) => {
		return fetch<T>(url, 'post', body, option)
	},

	put: <T>(url: string, body?: any, option?: UseFetchOptions<any>) => {
		return fetch<T>(url, 'put', body, option)
	},

	delete: <T>(url: string, body?: any, option?: UseFetchOptions<any>) => {
		return fetch<T>(url, 'delete', body, option)
	},
}
